package com.projecy.config.filter;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.projecy.common.constant.CommonConstants;
import com.projecy.common.constant.SecurityConstants;
import com.projecy.common.exception.BadRequestException;
import com.projecy.common.utils.JwtUtil;
import com.projecy.common.utils.RedisUtil;
import com.projecy.common.utils.SecurityUtil;
import com.projecy.system.service.SysMenuService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.CollectionUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;


public class JwtAuthorizationFilter extends BasicAuthenticationFilter {

    //JWT 的三个部分，Header（头部）， Payload（负载），Signature（签名）。
    //地址：https://github.com/rench/scio/tree/master/scio-cloud-jwt
    //https://www.jianshu.com/p/3703fe64cfc8
        @Autowired
    SysMenuService menuService;
  //Constructor Injection是构造器注入，是我们日常最为推荐的一种使用方式
    //地址：https://www.cnblogs.com/mili0601/p/15582421.html
      @Autowired
      RedisUtil redisUtil;



    public JwtAuthorizationFilter(AuthenticationManager authenticationManager, SysMenuService menuService, RedisUtil redisUtil) {
        super(authenticationManager);
        this.menuService = menuService;
        this.redisUtil = redisUtil;
    }


    @Override//过滤用户请求
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        System.out.println("过滤用户请求"+request.getRequestURI());
        try {
            //  从request中获取token
            String token = this.getTokenFromHttpServletRequest(request);
            //  校验token是否有效
            if (JwtUtil.verifyToken(token)){
                //  获取认证信息
                Authentication authentication = JwtUtil.getAuthentication(token);
                //  将认证信息保存在spring安全上下文中
                SecurityContextHolder.getContext().setAuthentication(authentication);
                //  校验访问权限（即使用token也需要对应的权限才能访问）
                if (!checkUri(request.getRequestURI())){
                    if (!checkUri(request.getRequestURI())) {
                        HttpServletRequestWrapper wrappedRequest = new HttpServletRequestWrapper(request) {
                            @Override
                            public String getRequestURI() {
                                return "/sys/menu/anomaly";
                            }
                        };
                        filterChain.doFilter(wrappedRequest, response);
                    }
                    throw new BadRequestException("没有访问权限");
                }
                //  放行请求
                System.out.println("放行URL"+request.getRequestURI());
//                HttpServletRequest reque = request;
                //
//                if (true) {
//                    HttpServletRequestWrapper wrappedRequest = new HttpServletRequestWrapper(request) {
//                        @Override
//                        public String getRequestURI() {
//                            return "/sys/menu/all";
//                        }
//
//                    };
//                    filterChain.doFilter(wrappedRequest, response);
//                }

                filterChain.doFilter(request, response);
            }
        } catch (BadRequestException e) {
            //  token问题,统一作401处理
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
        }
    }


    //从http中获取token
    private String getTokenFromHttpServletRequest(HttpServletRequest request){
        //  通过Authorization获取token
        System.out.println("从http中获取token,通过Authorization获取token");
        String authorization = request.getHeader(SecurityConstants.TOKEN_HEADER);
        if (StringUtils.isNotBlank(authorization) && authorization.startsWith(SecurityConstants.TOKEN_PREFIX)){
            return authorization.replace(SecurityConstants.TOKEN_PREFIX, "");
        }
        return null;
    }




    private boolean checkUri(String url){//校验访问的url,登录访问
        try {
            boolean b = false;
            if (SecurityUtil.getCurrentRoles().contains(CommonConstants.ROLE_ADMIN)){
                return true;//允许通过
            }
            //定义一个集合接收用户权限
            List<String> menuList;
            String menuKey = "menu_" + SecurityUtil.getCurrentUserId();
            //  从redis中取出用户的所有菜单及按钮权限
            menuList = Collections.singletonList(redisUtil.getValue(menuKey));
            //  如果redis为空
            if (CollectionUtils.isEmpty(menuList)){
                //  重新获取当前用户所有授权菜单
                menuList = menuService.getUrlsByRoles(SecurityUtil.getCurrentRoles());
                //  如果不为空
                if (!CollectionUtils.isEmpty(menuList)){
                    //  保存进redis中
                    redisUtil.setValue(menuKey, menuList, 7200L, TimeUnit.SECONDS);
                }
            }
            //校验url是否有权限放行
            b = checkRelease(url);
            if (menuList.contains(url)){
                b = true;
            }
            if (b==false){
                url = redisUtil.getUrl(menuKey+"URL");

            }else {
                redisUtil.setUrl(menuKey+"URL",url,1800L,TimeUnit.SECONDS);
            }

            return b;
        } catch (BadRequestException e) {
            e.printStackTrace();
            throw new BadRequestException(e.getMsg());
        }
    }
    private boolean checkRelease(String url){
        boolean b =false;
        if (url.indexOf("tree")!=-1||url.indexOf("/sys/role/table")!=-1||url.indexOf("/list")!=-1||url.indexOf("/sys/menu/all")!=-1
        ) {
            b = true;
        }
        //获取当前登录用户
        List<String> roles = SecurityUtil.getCurrentRoles();
        JSONArray jsonArray = menuService.getMenuTree(roles);
        System.out.println("jsonArray大小"+jsonArray.size());
        System.out.println(jsonArray);
        //通过迭代校验url决定是否放行
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject obj = jsonArray.getJSONObject(i);
            JSONArray children = obj.getJSONArray("children");
            System.out.println("children大小:"+children.size());
            for(int j=0; j<children.size(); j++) {
                JSONObject child = children.getJSONObject(j);
                System.out.println("child=="+child);
                JSONArray childrens = child.getJSONArray("children");
                for(int k=0; k<childrens.size();k++){
                    JSONObject childs = childrens.getJSONObject(k);
                    System.out.println("childs"+childs);
                    //判断是否是页面
                    if(childs.getString("type").equals("2")) {
                        System.out.println("children是否存在"+childs.containsKey("children"));
                        Boolean c =childs.containsKey("children");
                        //如果存在下一级子功能就进入
                        if (c == true) {
                            //取出children里面的菜单功能数据
                            JSONArray childrenss = childs.getJSONArray("children");
                            System.out.println(childrenss.size());
                            //遍历一下子功能，查看有几个模块
                            for (int q=0; q<childrenss.size(); q++) {
                                JSONObject objs = childrenss.getJSONObject(q);
                                //取出path数据进行校验
                                String path = objs.getString("path");
                                System.out.println("paths"+path);
                                System.out.println("URLs:==>"+url);
                                if(url.indexOf(path)!=-1){
                                    //如果有权限就放行
                                    b = true;
                                    System.out.println("path:==>"+path);
                                    System.out.println("URL:==>"+url);
                                }
                            }
                        }else {//存在下一级子功能就进入
                            //取出path数据进行校验
                            String path = childs.getString("path");
                            System.out.println("patha:==>"+path);
                            System.out.println("URLa:==>"+url);
                            if(url.indexOf(path)!=-1){
                                //如果有权限就放行
                                b = true;
                                System.out.println("path:==>"+path);
                                System.out.println("URL:==>"+url);
                            }
                        }
                        break;
                    }
                }
            }
        }
        System.out.println("return b"+b);
        return b;
    }
}
